package com.weds.frame.auth.interceptor;

import com.weds.frame.auth.config.JWTProperties;
import com.weds.frame.auth.entity.base.JWTParseResponse;
import com.weds.frame.auth.service.TokenService;
import com.weds.frame.core.exception.AuthenticationException;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Description:
 * Author: LiuWenQing
 * Datetime: 2023/3/17 14:27
 */
@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Autowired
    private TokenService tokenService;
    @Autowired
    private JWTProperties jwtProperties;
    private static List<Pattern> patterns = new ArrayList();
    private Logger log = LogManager.getLogger();

    @PostConstruct
    public void init() {
        if (null != this.jwtProperties && !StringUtils.isEmpty(this.jwtProperties.getFilter())) {
            String[] filters = this.jwtProperties.getFilter().split(",");
            String[] var3 = filters;
            int var4 = filters.length;

            for (int var5 = 0; var5 < var4; ++var5) {
                String filter = var3[var5];
                patterns.add(Pattern.compile(filter));
            }
        }

        patterns.add(Pattern.compile("v2/api-docs.*"));
        patterns.add(Pattern.compile("configuration/ui.*"));
        patterns.add(Pattern.compile("swagger-resources.*"));
        patterns.add(Pattern.compile("configuration/security.*"));
        patterns.add(Pattern.compile("swagger-ui.html"));
        patterns.add(Pattern.compile("spec"));
        patterns.add(Pattern.compile("healthy"));
        patterns.add(Pattern.compile("webjars.*"));
        patterns.add(Pattern.compile("error"));
        patterns.add(Pattern.compile("druid/*.*"));
        patterns.add(Pattern.compile("doc.html"));
        patterns.add(Pattern.compile("errorHtml"));
    }

    public AuthInterceptor() {
        super();
    }

    @Order(Integer.MIN_VALUE + 3)
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        /**
         * 过滤option请求
         */
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Methods", "*");
            response.setHeader("Access-Control-Allow-Headers",
                    request.getHeader("Access-Control-Request-Headers"));
            response.setStatus(HttpStatus.OK.value());
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }
        if (!(handler instanceof HandlerMethod)) {
            setCorsMappings(request, response);
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }
        String url = request.getRequestURI().substring(request.getContextPath().length());
        if (url.startsWith("/") && url.length() > 1) {
            url = url.substring(1);
        }

        if (!isInclude(url)) {
            long start = System.currentTimeMillis();
            String data = authorizationToken(tokenService, request, response);
            if ("-1".equals(data)) {
                log.error("令牌校验失败");
                throw new AuthenticationException("令牌校验失败");
            }
            reflectSetHeader(request, "pdata", data);
//            log.info("token鉴权耗时  {}  ms", System.currentTimeMillis() - start);
            return true;
        }
        return true;
    }

//    public void doAuthInterface(HttpServletRequest request, String data){
//        S
//    }

    public static String authorizationToken(TokenService tokenService, HttpServletRequest request, HttpServletResponse response) {
        String authHeader = request.getHeader("Authorization");
        if (StringUtils.isNotEmpty(authHeader)) {
            try {
                String credentials = new String(Base64.getDecoder().decode(authHeader.contains(" ") ? authHeader.split(" ")[1].trim() : authHeader.trim()), "UTF-8");
                JWTParseResponse jwtParseResponse = tokenService.parseToken(credentials);
                if ("0".equals(jwtParseResponse.getCode())) {
                    return jwtParseResponse.getPdata();
                }
                response.setStatus(401);
                return "-1";
            } catch (Exception e) {
                e.printStackTrace();
                response.setStatus(401);
            }
        }
        return "-1";
    }

    private boolean isInclude(String url) {
        Iterator var2 = patterns.iterator();

        Matcher matcher;
        do {
            if (!var2.hasNext()) {
                return false;
            }

            Pattern pattern = (Pattern) var2.next();
            matcher = pattern.matcher(url);
        } while (!matcher.matches());

        return true;
    }

    private void setCorsMappings(HttpServletRequest request, HttpServletResponse response) {
        String origin = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", origin);
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
        response.setHeader("Access-Control-Allow-Credentials", "true");
    }

    private void reflectSetHeader(HttpServletRequest request, String key, String value) {
        request.setAttribute(key,value);
//        InputStreamHttpServletRequestWrapper request1 = (InputStreamHttpServletRequestWrapper) request;
//            request1.addHeader(key, value);
//        Class<? extends HttpServletRequest> requestClass = request.getClass();
//        if (requestClass.getName().equals("com.weds.frame.common.entity.InputStreamHttpServletRequestWrapper")) {
//            InputStreamHttpServletRequestWrapper request1 = (InputStreamHttpServletRequestWrapper) request;
//            request1.addHeader(key, value);
//        } else {
//            try {
//                Field request1 = requestClass.getDeclaredField("request");
//                request1.setAccessible(true);
//                Object o = request1.get(request);
//                Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
//                coyoteRequest.setAccessible(true);
//                Object o1 = coyoteRequest.get(o);
//                Field headers = o1.getClass().getDeclaredField("headers");
//                headers.setAccessible(true);
//                MimeHeaders o2 = (MimeHeaders) headers.get(o1);
//                o2.removeHeader(key);
//                o2.addValue(key).setString(value);
//            } catch (Exception e) {
//                log.info("reflect set header error {}", e);
//            }
//        }
    }
}
